package com.wh.wisdomsite.xbox.server;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.wh.wisdomsite.xbox.ba.entity.AppMethod;
import com.wh.wisdomsite.xbox.ba.entity.AppSecret;
import com.wh.wisdomsite.xbox.ba.entity.ServiceMethod;
import com.wh.wisdomsite.xbox.ba.service.IAppMethodService;
import com.wh.wisdomsite.xbox.ba.service.IAppSecretService;
import com.wh.wisdomsite.xbox.ba.service.IServiceMethodService;
import com.wh.wisdomsite.xbox.pojo.ba.AppMethodIn;
import com.wh.wisdomsite.xbox.common.ServiceMethodHandler;
import com.wh.wisdomsite.xbox.common.util.ResManager;
import com.wh.wisdomsite.xbox.core.ServiceDispatcher;
import com.wh.wisdomsite.xbox.server.manager.SampleInvokeTimesController;
import com.wh.wisdomsite.xbox.server.manager.SampleServiceAccessController;
import com.wh.wisdomsite.xbox.utils.date.DateTool;
import com.wh.wisdomsite.xbox.utils.json.JsonUtil_Org;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 功能描述：应用－服务方法管理Controller
 * @Package com.wh.wisdomsite.xbox.server
 * @author 谢泽鹏
 * @date 2014年10月8日 下午4:02:14
 * @Copyright 个人版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2014
 * @version V1.0
 */
@Controller
@RequestMapping(value = "/appMethod")
public class AppMethodController {
    private static final Log logger = LogFactory.getLog(AppMethodController.class);

    @Autowired
    private IAppMethodService iAppMethodService;

    @Resource(name = "serviceDispatcher")
    private ServiceDispatcher serviceDispatcher;

    @Autowired
    private IServiceMethodService iServiceMethodService;

    @Autowired
    private IAppSecretService iAppSecretService;


    /**
     * 跳转页面到服务方法
     * @return
     */
    @RequiresPermissions("rules:dataService_appMehod_page")
    @RequestMapping(value = "index.do", method = RequestMethod.GET)
    public String index(){
        return "/dataServices/appMethod/appMethodList";
    }

    /**
     * 获取服务方法列表
     * @param response
     * @param in
     */
    @RequiresPermissions("rules:dataService_appMehod_find")
    @RequestMapping(value = "/appMethodAllList.do")
    public void appMethodAllList(HttpServletResponse response, AppMethodIn in){
        try {
            logger.info("加载服务方法数据列表-->>开始");
            //设置分页
            if(in.getPage() == 0) in.setPage(1);
            if(in.getRows() == 0) in.setRows(10);
            Page<AppMethod> page = new Page<AppMethod>();
            page.setCurrent(in.getPage());
            page.setSize(in.getRows());
            //设置条件
            EntityWrapper<AppMethod> ewAppMethod = new EntityWrapper<AppMethod>();
            ewAppMethod.setEntity(new AppMethod());
            if(StringUtils.isNotEmpty(in.getAppKey())){
                ewAppMethod.like("T_APP_KEY", in.getAppKey());
            }
            if(StringUtils.isNotEmpty(in.getMethod())){
                ewAppMethod.like("T_METHOD", in.getMethod());
            }
            ewAppMethod.orderBy("T_METHOD, T_CREATE_DATE", true);
            Page<AppMethod> appMethodPage = iAppMethodService.selectPage(page, ewAppMethod);
            JSONObject json = new JSONObject();
            JSONArray array = new JSONArray();
            if(appMethodPage.getRecords().size() > 0){
                for(AppMethod appMethod : appMethodPage.getRecords()){
                    JSONObject object = new JSONObject(appMethod);
                    object.put("id",appMethod.getId());
                    object.put("createDate", DateTool.format(appMethod.getCreateDate(), "yyyy-MM-dd HH:mm:ss"));
                    array.put(object);
                }
            }
            json.put("total", appMethodPage.getTotal());
            json.put("rows", array);
            ResManager.getTextOut(response).print(json);
            logger.info("加载服务方法数据列表-->>结束");
        }catch (Exception e){
            e.printStackTrace();
            logger.debug("加载服务方法数据列表-->>Exception" + e.getMessage());
        }

    }

    /**
     * 服务方法详情
     * @param appMethodIn
     * @param request
     * @return
     */
    @RequiresPermissions("rules:dataService_appMehod_view")
    @RequestMapping("appMethodDesc.do")
    public String appSecretDesc(AppMethodIn appMethodIn, HttpServletRequest request) {
        logger.info("服务方法详情-->>开始");
        AppMethod appMethod = iAppMethodService.selectById(appMethodIn.getId());
        request.setAttribute("appMethod", appMethod);
        request.setAttribute("createDate", DateTool.format(appMethod.getCreateDate(), "yyyy-MM-dd HH:mm:ss"));
        request.setAttribute("updateDate", DateTool.format(appMethod.getUpdateDate(), "yyyy-MM-dd HH:mm:ss"));
        logger.info("服务方法详情-->>结束");
        return "/dataServices/appMethod/appMethodDesc";
    }

    /**
     * 更新或者修改
     * @param appMethod
     * @param response
     * @throws Exception
     */
    @RequiresPermissions("rules:dataService_appMehod_edit")
    @RequestMapping(value = "/save.do", method = RequestMethod.POST)
    public void save(AppMethod appMethod, HttpServletResponse response){
        try {
            //查看方法是否已经存在
            if(StringUtils.isNotEmpty(appMethod.getId())){
                logger.info("修改服务方法-->>开始");
                appMethod.setUpdateDate(new Date());
                iAppMethodService.updateById(appMethod);
                logger.info("修改服务方法-->>结束");
                ResManager.getJsonOut(response).print(JsonUtil_Org.returnTrue("服务方法更新成功"));
            }else {
                logger.info("添加服务方法-->>开始");
                appMethod.setCreateDate(new Date());
                appMethod.setId(UUID.randomUUID().toString().replace("-",""));
                iAppMethodService.insert(appMethod);
                logger.info("添加服务方法-->>结束");
                ResManager.getJsonOut(response).print(JsonUtil_Org.returnTrue("添加服务方法成功"));
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.debug("操作服务方法-->>Exception" + e.getMessage());
        }
    }

    /**
     * 删除服务方法
     * @param id
     * @param response
     */
    @RequiresPermissions("rules:dataService_appMehod_del")
    @RequestMapping(value = "/del.do", method = RequestMethod.GET)
    public void del(String id, HttpServletResponse response){
        try{
            logger.info("删除服务方法-->>开始");
            iAppMethodService.deleteById(id);
            logger.info("删除服务方法-->>结束");
            ResManager.getJsonOut(response).print(JsonUtil_Org.returnTrue("服务方法删除成功"));
        } catch (Exception e){
            e.printStackTrace();
            logger.error("删除服务方法-->>Exception" + e.getMessage());
        }
    }

    /**
     * 重置服务方法
     * @return
     */
    @RequiresPermissions("rules:dataService_appMehod_res")
    @RequestMapping(value = "/resetAccessService.do", method = RequestMethod.GET)
    public void setAccessServiceMethod(HttpServletResponse response) {
        try {
            logger.info("重置服务方法-->>开始");
            //系统扫描注册的服务方法集合
            Map<String, ServiceMethodHandler> serviceMethodHandlerMap = serviceDispatcher.getXboxContext().getServiceHandlerMap();
            //应用密钥集合
            EntityWrapper<AppSecret> ewAppSecret = new EntityWrapper<AppSecret>();
            ewAppSecret.setEntity(new AppSecret());
            List<AppSecret> appSecretList = iAppSecretService.selectList(ewAppSecret);

            //数据库提取服务方法集合
            EntityWrapper<ServiceMethod> ewServiceMethod = new EntityWrapper<ServiceMethod>();
            ewServiceMethod.setEntity(new ServiceMethod());
            ewServiceMethod.orderBy("T_METHOD,T_VERSION", true);
            List<ServiceMethod> serviceMethodList = iServiceMethodService.selectList(ewServiceMethod);

            //数据库存储的应用－服务方法集合
            EntityWrapper<AppMethod> ewAppMethod = new EntityWrapper<AppMethod>();
            ewAppMethod.setEntity(new AppMethod());
            ewAppMethod.orderBy("T_APP_KEY,T_METHOD", true);
            List<AppMethod> appMethodList = iAppMethodService.selectList(ewAppMethod);

            //可访问服务方法匹配过程，只取交集
            Map<String, List<String>> serviceAccessMap = new HashMap<String, List<String>>();
            //日志记录  key会method与version的组合
            //Map<String, List<String>> logServiceMap = new HashMap<String, List<String>>();
            //应用请求次数限制
            Map<String, AtomicInteger> appCallLimits = new ConcurrentHashMap<String, AtomicInteger>();
            //app-method请求次数限制
            Map<String, AtomicInteger> appMethodCallLimits = new ConcurrentHashMap<String, AtomicInteger>();
            //app-method请求频率
            Map<String, AtomicInteger> appMethodCallRate = new ConcurrentHashMap<String, AtomicInteger>();
            //计算应用的请求次数的限制
            for (AppSecret appSecret : appSecretList) {
                if (appSecret.getStatus() == 1) {
                    appCallLimits.put(appSecret.getAppKey(), new AtomicInteger(appSecret.getLimit()));
                }
            }
            //计算应用对应服务方法的访问集合
            for (ServiceMethod sm : serviceMethodList) {
                String methodVersion = sm.getMethod() + "$" + sm.getVersion();
                //查看服务方法是否已注册
                if (serviceMethodHandlerMap.containsKey(methodVersion) && sm.getObsoleted() == 0) {
                    //判断应用-服务方法对应关系
                    for (AppMethod am : appMethodList) {
                        if (am.getMethod().equals(methodVersion) && am.getStatus() == 1) {
                            // 添加可访问的服务方法
                            if (serviceAccessMap.containsKey(am.getAppKey())) {
                                serviceAccessMap.get(am.getAppKey()).add(methodVersion);
                            } else {
                                List<String> methodVersionList = new ArrayList<String>();
                                methodVersionList.add(methodVersion);
                                serviceAccessMap.put(am.getAppKey(), methodVersionList);
                            }
                        }
                    }
                    //判断是否需要会话记录  TODO 暂进没有使用
                    if (sm.getNeedSession() == 1) {
                        serviceMethodHandlerMap.get(methodVersion).getServiceMethodDefinition().setNeedInSession(true);
                    } else {
                        serviceMethodHandlerMap.get(methodVersion).getServiceMethodDefinition().setNeedInSession(false);
                    }

                }
            }
            //加载应用对服务方法的请求频率和请求限制
            for (AppMethod am : appMethodList) {
                appMethodCallLimits.put(am.getAppKey() + "$" + am.getMethod(), new AtomicInteger(am.getTimes()));
                appMethodCallRate.put(am.getAppKey() + "$" + am.getMethod(), new AtomicInteger(am.getRate()));
            }
            ((SampleServiceAccessController) serviceDispatcher.getSecurityManager().getServiceAccessController()).setAccessServiceMethod(serviceAccessMap);
            ((SampleInvokeTimesController) serviceDispatcher.getSecurityManager().getInvokeTimesController()).setAppMethodCallLimit(appMethodCallLimits);
            ((SampleInvokeTimesController) serviceDispatcher.getSecurityManager().getInvokeTimesController()).setAppMethodCallRate(appMethodCallRate);
            ((SampleInvokeTimesController) serviceDispatcher.getSecurityManager().getInvokeTimesController()).setAppCallLimits(appCallLimits);
            ResManager.getJsonOut(response).print(JsonUtil_Org.returnTrue("重置服务方法成功"));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("重置服务方法-->>Exception" + e.getMessage());
        }
            logger.info("重置服务方法-->>结束");
    }


}
